home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / ODF & Cyberdog / CyberStarter / Sources / Part.cpp < prev    next >
Encoding:
Text File  |  1996-04-23  |  9.1 KB  |  259 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                Part.cpp
  4. //    Release Version:    $ ODF 1 $
  5. //
  6. //    Copyright:            (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. /*
  11.     To find portions of code dealing with code Cyberdog support, search for CYBERDOG.
  12.     This sample has a simple text model; the code is tagged with CONTENTDATA.
  13.     Some constants *must* be changed by you to make a proper part. Search for MUSTCHANGE
  14.     Some threaded stuff is delimited by USETHREADSFLAG but is not finished in this version
  15.     of the code base.
  16. */
  17.  
  18. #include "Part.h"
  19. #include "Frame.h"
  20. #include "Define.h"
  21. #include "Binding.h"
  22.  
  23. #include "Cyberdog.h"
  24. #include "CyberSession.xh"
  25. #include "CyberStream.xh"
  26. #include "CyberItem.xh"
  27.  
  28. #include "FWContxt.h"
  29. #include "FWIters.h"
  30.  
  31. #ifdef FW_BUILD_MAC
  32. #pragma segment CPart
  33. #endif
  34.  
  35. FW_DEFINE_AUTO(CPart)
  36.     
  37. /*----------------------------------------------------------------------------------------
  38.     Utilities
  39. ----------------------------------------------------------------------------------------*/
  40.  
  41. static void ImmediateRedrawPresentation (Environment* ev, FW_CPresentation* p)
  42. {
  43.     FW_CPresentationFrameIterator piter (ev, p);
  44.     for (FW_CFrame* frame = piter.First(ev); piter.IsNotComplete(ev); frame = piter.Next(ev)) {
  45.         FW_CFrameFacetIterator fiter (ev, frame);
  46.         for (ODFacet* facet = (ODFacet*) fiter.First(ev); fiter.IsNotComplete(ev); facet = fiter.Next(ev)) {
  47.             FW_CViewContext gc (ev, frame, facet, nil); 
  48.             ((CFrame*)frame)->DrawUpdate (ev, gc);
  49.         }
  50.     }
  51. }
  52.  
  53. //----------------------------------------------------------------------------------------
  54. // Standard Part Support
  55. //----------------------------------------------------------------------------------------
  56.  
  57. CPart::CPart(ODPart* odPart)
  58. :    FW_CPart(odPart, FW_gInstance, kPartInfoID)
  59. ,    FW_MCyberPart (this) // CYBERDOG
  60. #if !USETHREADSFLAG
  61. ,    FW_CIdler (this, 6) // idling 10 times a second should be Ok
  62. ,    fStream (nil)
  63. #endif
  64. ,    fDownloadedText (nil)
  65. {
  66. }
  67.  
  68. CPart::~CPart()
  69. {
  70.     ::DisposeHandle (fDownloadedText);
  71. }
  72.  
  73. void CPart::Initialize(Environment* ev)
  74. {
  75.     FW_CPart::Initialize (ev);
  76.     FW_MCyberPart::Initialize (ev);// CYBERDOG
  77.     fPresentation = RegisterPresentation(ev, kODPresDefault, TRUE);
  78.     
  79.     // I think it's simpler to have a 0-length handle than a null handle
  80.     fDownloadedText = ::NewHandle(0);
  81.     
  82. //    RegisterIdle (ev); // HACK to work around an ODF R1c9 bug
  83. }
  84.  
  85. FW_CFrame* CPart::NewFrame(Environment* ev, 
  86.                                   ODFrame* odFrame, 
  87.                                   FW_CPresentation* presentation, 
  88.                                   FW_Boolean fromStorage)
  89. {
  90.     FW_UNUSED(presentation);
  91.     FW_UNUSED(fromStorage);
  92.     
  93.     return FW_NEW(CFrame, (ev, odFrame, presentation, this));
  94. }
  95.  
  96. FW_CContent* CPart::NewPartContent(Environment* ev)
  97. {
  98.     return NULL;
  99. }
  100.  
  101. void CPart::ExternalizeContent (Environment* ev, ODStorageUnit* su, FW_CCloneInfo* cloneInfo)
  102. {
  103.     // Before calling ExternalizeContent, FW_CODPart calls PrivCleanseContentProperty.
  104.     // FW_CPart::ExternalizeContent then calls ClearPartStorage. These amount to an 
  105.     // expensize ODSURemoveProperty. RFE
  106.     ODSURemoveProperty (ev, su, kODPropContents);
  107.     
  108.     // Save content. Pure text, no other data, to make sure our data can be read by any other part.
  109.     ODSUForceFocus (ev, su, kODPropContents, kKind);
  110.     FW_PStorageUnitSink sink (ev, su, kODPropContents, kKind);
  111.     FW_CAcquireLockedSystemHandle locked (fDownloadedText);
  112.     sink->Write (ev, *fDownloadedText, GetHandleSize(fDownloadedText));
  113. }
  114.  
  115. void CPart::InternalizeContent(Environment* ev, ODStorageUnit* su, FW_CCloneInfo* cloneInfo)
  116. {
  117.     // Read our content (if any).
  118.     if (ODSUExistsThenFocus (ev, su, kODPropContents, kKind)
  119.             || ODSUExistsThenFocus (ev, su, kODPropContents, FW_CPart::gMacTEXTDataType)) {
  120.         Size size = su->GetSize (ev);
  121.         ::SetHandleSize (fDownloadedText, size);
  122.         FW_CAcquireLockedSystemHandle locked (fDownloadedText);
  123.         FW_PStorageUnitSink sink (ev, su, kODPropContents, kKind);
  124.         sink->Read (ev, *fDownloadedText, size);
  125. //        FW_CByteArray bytes;
  126. //        su->GetValue (ev, size, bytes);
  127. //        bytes.CopyBuffer (*fDownloadedText, size);
  128.     }
  129.     else if (ODSUExistsThenFocus (ev, su, kODPropContents, FW_CPart::gMacTEXTFileType)) {
  130.     }
  131. }
  132.  
  133. /*----------------------------------------------------------------------------------------
  134.     CYBERDOG
  135.     
  136.     You need to change DoIdle/LoadCyberItem to read your content from the network.
  137.     
  138.     DoSetCyberItem is called when you need to read a CyberItem. It starts idling,
  139.     and you will read the data in DoIdle. If you are using threads (preferred but not
  140.     quite handled properly by Cyberdog yet), then you will do the work in LoadCyberItem.
  141.     
  142.     Note that you must call inherited to get the default behavior of OpenCyberItem as 
  143.     well. Navigator-aware parts will not call inherited but will do things differently.
  144. ----------------------------------------------------------------------------------------*/
  145.  
  146. void CPart::DoSetCyberItem (Environment* ev, CyberItem* newItem, ParameterSet* parameters)
  147. {
  148.     // CYBERDOG - you don't need to change this method
  149.     
  150. #if !USETHREADSFLAG
  151.     // Create the stream and start idling. We read during idles. After we
  152.     // have all the data we'll delete the stream and stop idling.
  153.     fStream = newItem->CreateCyberStream (ev);
  154.     RegisterIdle (ev); // work-around for bug in ODF R1c9
  155.     ::SetHandleSize (fDownloadedText, 0);
  156. #else
  157.     // Create a new thread to read the data. It won't start reading until shortly after 
  158.     // we return from this method, so we can't pass in any stack-based parameters.
  159.     FW_NewThread (&LoadCyberItem, this);
  160. #endif
  161. }
  162.  
  163. void CPart::HandleOpenCyberItem (Environment* ev, CyberItem* item, ODPart* openerPart, ParameterSet* how)
  164. {
  165.     // If you want to be a standard Cyber-savvy part then you must call inherited to get 
  166.     // the default behavior. Navigator-savvy parts will do things differently (XXX to do!)
  167.     FW_MCyberPart::HandleOpenCyberItem (ev, item, openerPart, how);
  168. }
  169.  
  170. #if !USETHREADSFLAG
  171.  
  172. FW_Boolean CPart::DoIdle (Environment* ev, const FW_CNullEvent& event)
  173. {
  174.     if (fStream) {
  175.         short status = fStream->GetStreamStatus (ev);
  176.         if (status & kCDDataAvailable) {
  177.             Size oldSize = ::GetHandleSize (fDownloadedText);
  178.             FW_CCyberBuffer ab (ev, fStream);
  179.             // CONTENTDATA - change this portion to deal with your data form
  180.             // Add any data available to the text handle, and redraw it
  181.             ::SetHandleSize (fDownloadedText, oldSize + ab.GetSize());
  182.             if (::MemError()) // XXX what's the best way to report an error from an idle method?
  183.                 status = kCDErrorOccurred;
  184.             else
  185.                 memcpy (*fDownloadedText + oldSize, ab.GetBuffer(), ab.GetSize());
  186.             // Draw the new data right now
  187.             ImmediateRedrawPresentation (ev, fPresentation);
  188.         }
  189.         
  190.         if (status & FW_kCyberStreamDone) {
  191.             fStream = nil; // smart pointer, will call Abort if necessary automatically
  192.             UnregisterIdle (ev); // work-around for bug in ODF R1c9
  193.         }
  194.     }
  195.     
  196.     return false; // let other idlers get time also XXX need FW_kContinueEvent!
  197. }
  198.  
  199. #else
  200.  
  201. pascal void* CPart::LoadCyberItem (void* selfCPart)
  202. {
  203.     // XXX this method probably does not compile! Threads support is broken in
  204.     // Cyberdog at this moment and therefore this sample hasn't been updated for it.
  205.     // Check the ODF web site (www.devtools.apple.com/odf) for updates.
  206.     
  207.     CPart* self = (CPart*) selfCPart;
  208.     Environment* ev = somGetGlobalEnvironment();
  209.     
  210.     // Note this is a static method. "this" is passed in from HandleOpenCyberItem/NewThread
  211.     
  212.     CyberItem* item = self->CurrentCyberItem();
  213.     CyberStream* cStream = item->CreateCyberStream (ev);
  214.     FW_CCyberSink sink (cStream);
  215.     
  216.     // Note that we're not trying to read any specific number of bytes of data. That
  217.     // could cause us to sleep. However, if there isn't *any* data, then we will sleep
  218.     // until at least one byte arrives.
  219.     
  220.     // We don't need to deal with error handling at all here. An error causes an
  221.     // exception to be thrown, and all our nice stack-based objects delete themselves.
  222.     
  223.     long total = 0;
  224.     long available;
  225.     while (available = sink.GetAvailableBytes (FW_CCyberSink::kSleepIfNoData)) {
  226.         // CONTENTDATA - change this portion to deal with your data form
  227.         // We'll download and display whatever is available.
  228.         ::SetHandleSize (self->fDownloadedText, total + available);
  229.         ::HLock(self->fDownloadedText);
  230.         sink.Read (*self->fDownloadedText + total, available);
  231.         ::HUnlock (self->fDownloadedText);
  232.         total += available;
  233.         // Draw the new data right now
  234.         ImmediateRedrawPresentation (self->fPresentation);
  235.     }
  236.     
  237.     return nil;
  238. }
  239.  
  240. #endif
  241.  
  242. FW_CEventDispatcher* CPart::PrivNewEventDispatcher(Environment *ev)
  243. {
  244.     // CYBERDOG - you do not need need to change this method
  245.     
  246.     // Cyberdog goes to considerable lengths to work around OpenDoc problems. One
  247.     // of these is that OpenDoc wants to put everything in a Bento document.
  248.     // Cyberdog makes it's own Draft subclass which is not disk based, and 
  249.     // instantiates all parts into that. Unfortunately this is NOT transparent. We
  250.     // are required to let Cyberdog close windows for any of these parts; if 
  251.     // OpenDoc sees them it gets very confused.
  252.     // This means we need to intercept close-box and command-W events. Command-W
  253.     // is easy, but close-box events require us to subclass ODF's event dispatcher
  254.     // class. This will be fixed for the next release of ODF.
  255.     
  256.     return FW_MCyberPart::MakeEventDispatcher (ev);
  257. }
  258.  
  259.